#ifndef COMMON__H
#define COMMON__H

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <stdbool.h>

//#define DEBUG
//#define LESS
//#define RELOP_DETAIL

#ifdef DEBUG
#define DBG_printf(...) printf(__VA_ARGS__)
#else 
#define DBG_printf(...) ((void)0)
#endif

#define LOG(fmt,...) DBG_printf(fmt "\n",##__VA_ARGS__)

#define Assert(cond,fmt,...) \
    do{\
        if(!(cond)){\
            LOG(fmt,##__VA_ARGS__);\
        }\
        assert(cond);\
    } while (0)
    
#define Panic(fmt,...) Assert(0, fmt , ##__VA_ARGS__)

#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))

#define NEW(name,type) type * name = malloc(sizeof( type )) 
#define NEW_V(name,type,...)\
    NEW(name,type);\
    *name = ( type ){ __VA_ARGS__ };
#define SET_V(name,type,...)\
    name = malloc(sizeof( type ));\
    *name = ( type ){ __VA_ARGS__ };

#define DELETE(name) free(name)

typedef long long LL;
typedef unsigned long long uLL;

const char * str_maker(const char *,...);
const char * deep_copy(const char * );

typedef struct list_ * list;
struct list_{
    void * pointer;
    list nxt,prev;  
};
typedef struct{
    list begin,end;
}List;
List list_insert(List,void *);
List list_delete(List,list);
void list_clear(List);

#define LIST_INSERT(self,x) self = list_insert((self),(void *)(x))
#define LIST_DELETE(self,x) self = list_delete((self),(x))
#define LIST_GET(self,type) ((type)( (self) -> pointer))
#define LIST_EMPTY(self) ((self).begin==NULL && (self).end==NULL)
#define LIST_CLEAR(self) list_clear(self),self=(List){NULL,NULL}
#define FOR_LIST_2(now,self,nxt) for(list now = (self).begin; now ; now = (nxt)) 
#define FOR_LIST(now,self) FOR_LIST_2(now,self,now->nxt)
#define FOR_LIST_BACK_2(now,self,prev) for(list now=(self).end ; now ; now = (prev))
#define FOR_LIST_BACK(now,self) FOR_LIST_BACK_2(now,self,now->prev)


enum IR_RELOP_TYPE{
    IR_RELOP_EQ,IR_RELOP_NE,IR_RELOP_GT,IR_RELOP_GE,IR_RELOP_LT,IR_RELOP_LE
};

#endif
